#-*- coding: utf-8 -*-

import sys

from PyQt4 import QtCore
from PyQt4 import QtGui
from appGui import Ui_moodleed
from newQuestionGui import Ui_newQuestion
from questions import *
from questionsData import QuestionContainer
import getopt
import platform

__version__ = "0.9"


questionList = {
    "shortAnswer": Short_Answer,
    "multipleChoice": Multiple_Choice,
    "multipleAnswer": Multiple_Answer,
    "trueFalse": True_False,
    "matching": Matching
    }


class MainWindow(QtGui.QMainWindow):

    def __init__(self):
        QtGui.QMainWindow.__init__(self)

        # sprava otevrenych otazek
        self.questions = QuestionContainer(questionList)

        QtCore.QObject.connect(self.questions, QtCore.SIGNAL("questions ()"), self.updateWindow)
        
        # GUI aplikace
        self.ui = Ui_moodleed()
        self.ui.setupUi(self)
        self.initStatusbar()
        
        # dialog pro vyber nove otazky
        self.newQuestionDialog = NewQuestionDialog()
        # defaultni nastaveni indexu aktualniho question widgetu, pri zmene widgetu se tato hodnota meni
        self.currentWidgetIndex = 0

        # nastaveni velikost, pozice a stavu okna
        settings = QtCore.QSettings()
        size = settings.value("MainWindow/Size", QtCore.QVariant(QtCore.QSize(620, 420))).toSize()
        self.resize(size)
        position = settings.value("MainWindow/Position", QtCore.QVariant(QtCore.QPoint(0, 0))).toPoint()
        self.move(position)
        self.restoreState(settings.value("MainWindow/State").toByteArray())

    def bar(self):
        print "moooore ti to fachci"

    @QtCore.pyqtSlot()
    def newQuestionDialog(self):
        """
            TODO
        """
        # TODO komentare
        if self.newQuestionDialog.exec_():
            choices = self.newQuestionDialog.ui.choices.findChildren(QtGui.QRadioButton)
            type = self._getSelectedQuestion(choices)

            # vytvorime instanci otazky
            try:
                question = questionList[type]()
                # vlozime do otazky defaultni pocet odpovedi
                # ono tohle neni nejlepsi misto kde tu metodu volat, ale je to takhle nejjednodussi
                # kdybych to flaknul do drawQuestion, tak by se otazky vlozily i pri otevirani souboru a to nechci
                question.initAnswers()
                
            except KeyError:
                raise ValueError, "Unkown type of question."
            self.questions.add(question)
            self.drawQuestion(question)
            self.updateStatusbarQuestionCount()


    def drawQuestion(self, question, focus=True, title=None):
        """
            TODO
        """
        # title = text do polozky pro vyber otazky v comboboxu, pro vytvareni nove prazdne ma hodnotu None a nahradi se defaultnim textem \
        # pri vytvareni otazky nahranim existujici ze souboru se tam soupne bud titulek pokud existuje, jinak default
        # TODO dopsat komentar

        # zjistime jak je to s tim titulkem
        if not title:
            title = self.tr("Please enter name or text of question.")
        #question = questionList[type]()
        #self.questions.add(question)
        self.ui.questions.addWidget(question)
        self.ui.questionComboBox.addItem(title)

        # zmena titulku otazky zavola aktualizaci jejiho nazvu v ComboBoxu
        QtCore.QObject.connect(question.ui.questionTitle, QtCore.SIGNAL("textChanged(QString)"), self._updateQuestion)
        QtCore.QObject.connect(question.ui.question, QtCore.SIGNAL("textChanged()"), self._updateQuestion)

        # zapnuti checkboxu a comboboxu pro manipulaci s otazkami
        self.ui.questionSelector.setEnabled(True)
        self.ui.questionComboBox.setEnabled(True)

        if focus:
            #nastaveni prave vlozene otazky jako aktualni widget
            self.ui.questions.setCurrentWidget(question)


    def okToContinue(self):
        """ zkontroluje jestli probehly nejake zmeny od posledniho ulozeni, pokud ano, vrati dialog s moznosti ulozeni, pokud ne, vrati pravdu """

        if self.questions.isChanged():
            reply = QtGui.QMessageBox.question(self,
                                               self.tr("Questions - Unsaved Changes"),
                                               self.tr("Save unsaved changes?"),
                                               QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel)
            if reply == QtGui.QMessageBox.Cancel:
                return False
            elif reply == QtGui.QMessageBox.Yes:
                self.fileSave()

        return True


    @QtCore.pyqtSlot(name="on_actionSave_triggered")
    def fileSave(self):
        """ ulozi otazky """

        if self.questions.filename().isEmpty():
            self.fileSaveAs()
        else:
            ok, msg = self.questions.save()


    @QtCore.pyqtSlot(name="on_actionSave_as_triggered")
    def fileSaveAs(self):
        """ otevre save dialog, nastavi nazev ukladaneho souboru a ulozi """

        # pokud je nastaven nejaky nazev tak ho berem, pokud ne, tak to bude tecka
        fname = self.questions.filename() if not self.questions.filename().isEmpty() else "."
        fname = QtGui.QFileDialog.getSaveFileName(self,
                                                  self.tr("Save as ..."), fname,
                                                  self.tr("GIFT text files (%s)" % self.questions.formats()))
        if not fname.isEmpty():
            if not fname.contains("."):
                fname += ".txt"
            ok, msg = self.questions.save(fname)
            self.ui.statusbar.showMessage(msg, 5000)


    @QtCore.pyqtSlot(name="on_actionOpen_file_triggered")
    def fileOpen(self):
        """ otevira soubor s otazkami """

        if not self.okToContinue():
            return
        path = QtCore.QFileInfo(self.questions.filename()).path() if not self.questions.filename().isEmpty() else "."
        fname = QtGui.QFileDialog.getOpenFileName(self,
            self.tr("Load Question File"), path,
            self.tr("GIFT text files (%1)").arg(self.questions.formats()))
        self.deleteAllQuestion()
        ok, msg = self.questions.load(fname)
        if ok:
            for question in self.questions:
                #print "zadani: %s\ttitulek: %s\ttyp: %s\todp: %s" % (question.text.toUtf8(), question.title.toUtf8(), question.type, question.answers.getAnswers())
                self.drawQuestion(question, focus=None, title=question.title)
            # vykucham nazev souboru a upravim titulek okna
            #self.setWindowTitle(QtCore.QString("%1 - MoodleEd").arg(fname.split("/").last()))
            self.setWindowTitle(QtCore.QString("%1 - MoodleEd").arg(QtCore.QFileInfo(fname).fileName()))
        self.updateStatusbarQuestionCount()
        self.ui.statusbar.showMessage(msg, 5000)


    @QtCore.pyqtSlot()
    def _questionWidgetChanged(self, int):
        """ Funkce je volana vzdy pri zmene widgetu s otazkou """

        # aktualizace typu otazky ve statusbaru
        self.updateStatusbarQuestionType()
        #nevim jestli je to uplne dobry napad, ale udrzuju si tady aktualni index
        # pri zmene widgetu se zmeni na aktualni a tady ho chytim, tak snad to nebude delat paseku
        self.currentWidgetIndex = int
        # ve status baru se zobrazuje nazev typu otazky v aktualnim tabu
        try:
            # zaskrtnuti/odskrnuti checkboxu
            self.ui.questionSelector.setChecked(self.ui.questions.currentWidget().checked)
        # Kdyz se smaze posledni widget
        except AttributeError:
            pass


    @QtCore.pyqtSlot()
    def _updateQuestion(self, text=None):
        """ zaktualizuje text comboBoxu pri zmene/vytvoreni textu zadani otazky"""

        # TODO: nedalo by se to tady trochu zkulturnit ?

        # pokud byla metoda zavolana z widgetu se jmenem otazky
        if self.sender().objectName() == "questionTitle":
            # kouknem jestli neni nahodou $text prazdna, treba pri smazani jmena otazky, potom bude titulkem text otazky
            if text == None or text == "":
                questionComboBoxTitle = self.ui.questions.currentWidget().ui.question.toPlainText()
            else:
                # ale jinak bude v comboBoxu otazka oznacena textem z widgetu pro nazev otazky
                questionComboBoxTitle = text

        # ale pokud metodu zavolal widget s textem otazky
        elif self.sender().objectName() == "question":
            # zjistime jestli neco je v nazvu otazky
            questionTitle = self.ui.questions.currentWidget().ui.questionTitle.text()
            # pokud neni zadan nazev otazky, do comboboxu nacpem kus textu
            if questionTitle == "":
                questionComboBoxTitle = self.ui.questions.currentWidget().ui.question.toPlainText()
            # ale pokud je vyplnen nazev otazky, tak ma prednost
            else:
                questionComboBoxTitle = questionTitle

        # questionComboBoxTitle je to, co se zobrazi v comboBoxu
        self.ui.questionComboBox.setItemText(self.currentWidgetIndex, questionComboBoxTitle)


    @QtCore.pyqtSlot()
    def _questionSelectorChanged(self, state):
        # 2 - zaskrtnuti checkboxu / True do itemData
        # 0 - odskrtnuti checkboxu / False do itemData
        data = {2: True,
                0: False}
        self.ui.questions.currentWidget().checked = data[state]


    def _getSelectedQuestion(self, choices):
        """ najde ktery radioButton byl pri vyberu typu otazky oznacen """

        for radio in choices:
            if radio.isChecked():
                selectedQuestionType = radio.objectName()

        return str(selectedQuestionType)
    

    @QtCore.pyqtSlot(name="on_actionDelete_question_triggered")
    def deleteQuestion(self, question=None):
        """ mazani otazky """

        # pokud mame zadano kterou otazku maznout, tak berem ji, jinak smaze aktualni widget stackedlayoutu
        if not question:
            question = self.ui.questions.currentWidget()
        # smaznem polozku otazky v comboboxu, potrebujeme k tomu index widgetu otazky
        questionIndex = self.ui.questions.indexOf(question)
        self.ui.questionComboBox.removeItem(questionIndex)
        # smazani objektu otazky z vnitrniho seznamu otazek
        self.questions.delete(id(question))
        # smazani samotneho widgetu ze stackedlayoutu
        self.ui.questions.removeWidget(question)

        # pokud jsme smazali vsechno, vypneme nektere widgety
        if len(self.questions) == 0:
            self.ui.questionComboBox.setDisabled(True)
            #self.ui.questionSelector.setChecked(False)
            self.ui.questionSelector.setDisabled(True)

        self.updateStatusbarQuestionCount()


    @QtCore.pyqtSlot(name="on_actionDelete_all_triggered")
    def deleteAllQuestion(self):
        for question in self.questions:
            self.deleteQuestion(question)


    @QtCore.pyqtSlot(name="on_actionDelete_selected_triggered")
    def deleteSelectedQuestion(self):
        for question in self.questions:
            if question.checked:
                self.deleteQuestion(question)


    def initStatusbar(self):
        """ vlozeni par widgetu do statusbaru """

        # zobrazuje pocet vytvorenych otazek
        self.questionCounter = QtGui.QLabel(self)
        self.questionCounter.setText(self.tr("Questions: %1").arg(len(self.questions)))
        self.questionCounter.setToolTip(self.tr("Number of questions."))
        self.questionCounter.setFrameShape(QtGui.QFrame.Box)
        self.questionCounter.setFrameShadow(QtGui.QFrame.Sunken)

        # zobrazuje typ otazky
        self.questionTypeWidget = QtGui.QLabel(self)
        self.questionTypeWidget.setText(self.tr("No question"))
        self.questionTypeWidget.setToolTip(self.tr("Type of question."))
        self.questionTypeWidget.setFrameShape(QtGui.QFrame.Box)
        self.questionTypeWidget.setFrameShadow(QtGui.QFrame.Sunken)

        self.ui.statusbar.addPermanentWidget(self.questionTypeWidget)
        self.ui.statusbar.addPermanentWidget(self.questionCounter)


    def updateStatusbarQuestionCount(self):
        """ nazev metody je myslim dostatecne vystizny .. """

        self.questionCounter.setText(self.tr("Questions: %1").arg(len(self.questions)))


    def updateStatusbarQuestionType(self):
        """ celkem jasne co tohle asi tak muze delat :) """

        # try jsem pouzil proto, ze kdyz se smazou vsechny otazky, tak neni co zjistovat
        try:
            currentQuestionType = self.ui.questions.currentWidget().questionName
        except AttributeError:
            currentQuestionType = QtCore.QString(self.tr("No Question"))
        self.questionTypeWidget.setText(currentQuestionType)
        

    def updateWindow(self):
        """ aktualizuje okno """

        # zmeni titulek okna, za nazev otevreneho souboru v titulku vlozi "[changed]" text
        if self.questions.isChanged():
            self.setWindowTitle(QtCore.QString("%1 %2 - MoodleEd").arg(QtCore.QFileInfo(self.questions.filename()).fileName()).arg(self.tr("[changed]")))
        else:
            self.setWindowTitle(QtCore.QString("%1 - MoodleEd").arg(QtCore.QFileInfo(self.questions.filename()).fileName()))


    def closeEvent(self, event):
        """ vola se pri zavreni aplikace """

        if self.okToContinue():
            settings = QtCore.QSettings()
            settings.setValue("MainWindow/Size", QtCore.QVariant(self.size()))
            settings.setValue("MainWindow/Position", QtCore.QVariant(self.pos()))
            settings.setValue("MainWindow/State", QtCore.QVariant(self.saveState()))
        else:
            event.ignore()

    @QtCore.pyqtSlot(name="on_actionAbout_app_triggered")
    def helpAbout(self):
        QtGui.QMessageBox.about(self, self.tr("GiftEd - About"),
            self.tr("""
            <h1>GiftEd</h1>
            <p>Version %1</p>
            <p>Tool for creating files with questions in GIFT format for the LMS Moodle.</p>
            <p>(C) 2009-2010 Martin Stiborsky <br/>
            <a href="mailto:martin.stiborsky@gmail.com">martin.stiborsky@gmail.com</a><br/>
            <a href="http://www.twitter.com/stibi">http://www.twitter.com/stibi </a>
            </p>
            <p>
            <h3>Thanks to:</h3>
            <br/>
            Adam Tomecek - <a href="mailto:adam.tomecek@gmail.com">adam.tomecek@gmail.com</a> - CZ-ENG translations<br/>
            </p>
            <p>License: GNU General Public License Version 2</p>
            <p>Python %2 - Qt %3 - PyQt %4 on %5</p>
            """).arg(__version__).arg(platform.python_version()).arg(QtCore.QT_VERSION_STR).arg(QtCore.PYQT_VERSION_STR).arg(platform.system()))


class NewQuestionDialog(QtGui.QDialog):
    """ kresli okynko s dialogem pro vyber nove otazky """

    def __init__(self):
        QtGui.QDialog.__init__(self)


        # grafika
        self.ui = Ui_newQuestion()
        self.ui.setupUi(self)


def main(argv):
    # promenna ktera ridi nastaveni jazyka aplikace
    # nastavim ji na None, pockam jestli probehne zmena pres argument, pokud ne, nastavim ji na hodnotu kterou vrati locale() systemu
    language = None
    if argv:
        try:
            opts, args = getopt.getopt(argv, "hl:")
        except getopt.GetoptError:
            usage()
            sys.exit(2)

        for opt, arg in opts:
            if opt in ("-h"):
                usage()
                sys.exit(2)
            elif opt == "-l":
                language = arg

    locale = QtCore.QLocale.system().name()
    app = QtGui.QApplication(sys.argv)
    app.setOrganizationName("stibiApp")
    #app.setOrganizationDomain("stibi.cz")
    settings = QtCore.QSettings()
    if language:
        settings.setValue("Application/Language", language)
    else:
        settings.setValue("Application/Language", locale)

    qtTranslator = QtCore.QTranslator()
    if qtTranslator.load("qt_%s" % settings.value("Application/Language", QtCore.QLocale.system().name()).toString(), ":/translations/"):
        app.installTranslator(qtTranslator)
        
    appTranslator = QtCore.QTranslator()
    if appTranslator.load("app_%s" % settings.value("Application/Language", QtCore.QLocale.system().name()).toString(), ":/translations/"):
        app.installTranslator(appTranslator)

    app.setApplicationName("MoodleEd")
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

def usage():
    print "TODO !!!"

if __name__ == "__main__":
    main(sys.argv[1:])
